home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-10-20 | 53.9 KB | 1,810 lines |
- Newsgroups: comp.sources.misc
- From: kirsch@usasoc.soc.mil (David Kirschbaum)
- Subject: v23i094: zip - Portable zip v1.0, Part07/09
- Message-ID: <1991Oct21.042217.8186@sparky.imd.sterling.com>
- X-Md4-Signature: 6773101a8911f04410c9cf3dd6939e08
- Date: Mon, 21 Oct 1991 04:22:17 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: kirsch@usasoc.soc.mil (David Kirschbaum)
- Posting-number: Volume 23, Issue 94
- Archive-name: zip/part07
- Environment: UNIX, Minix, MSDOS, OS/2, VMS
-
- #! /bin/sh
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: ziperr.h zipfile.c zipsplit.c zipup.c
- # Wrapped by kent@sparky on Sun Oct 20 22:58:55 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 7 (of 9)."'
- if test -f 'ziperr.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ziperr.h'\"
- else
- echo shar: Extracting \"'ziperr.h'\" \(2561 characters\)
- sed "s/^X//" >'ziperr.h' <<'END_OF_FILE'
- X/*
- X
- X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
- X Permission is granted to any individual or institution to use, copy, or
- X redistribute this software so long as all of the original files are included
- X unmodified, that it is not sold for profit, and that this copyright notice
- X is retained.
- X
- X*/
- X
- X/*
- X * ziperr.h by Mark Adler.
- X */
- X
- X/* Error return values. The values 0..4 and 12..18 follow the conventions
- X of PKZIP. The values 4..10 are all assigned to "insufficient memory"
- X by PKZIP, so the codes 5..10 are used here for other purposes. */
- X#define ZE_MISS -1 /* used by procname(), zipbare() */
- X#define ZE_OK 0 /* success */
- X#define ZE_EOF 2 /* unexpected end of zip file */
- X#define ZE_FORM 3 /* zip file structure error */
- X#define ZE_MEM 4 /* out of memory */
- X#define ZE_LOGIC 5 /* internal logic error (implode) */
- X#define ZE_BIG 6 /* entry too large to split */
- X#define ZE_NOTE 7 /* invalid comment format */
- X#define ZE_ABORT 9 /* user interrupt or termination */
- X#define ZE_TEMP 10 /* error using a temp file */
- X#define ZE_READ 11 /* read or seek error */
- X#define ZE_NONE 12 /* nothing to do */
- X#define ZE_NAME 13 /* missing or empty zip file */
- X#define ZE_WRITE 14 /* error writing to a file */
- X#define ZE_CREAT 15 /* couldn't open to write */
- X#define ZE_PARMS 16 /* bad command line */
- X#define ZE_OPEN 18 /* could not open a specified file to read */
- X/* Macro to determine whether to call perror() or not */
- X#define PERR(e) (e==ZE_READ||e==ZE_WRITE||e==ZE_CREAT||e==ZE_TEMP||e==ZE_OPEN)
- X
- X#ifdef GLOBALS
- X/* Error messages for the err() function in the zip programs */
- Xchar *errors[] = {
- X/* 1 */ "",
- X/* 2 */ "Unexpected end of zip file",
- X/* 3 */ "Zip file structure invalid",
- X/* 4 */ "Out of memory",
- X/* 5 */ "Internal logic error",
- X/* 6 */ "Entry too big to split",
- X/* 7 */ "Invalid comment format",
- X/* 8 */ "",
- X/* 9 */ "Interrupted",
- X/* 10 */ "Temporary file failure",
- X/* 11 */ "Input file read failure",
- X/* 12 */ "Nothing to do!",
- X/* 13 */ "Missing or empty zip file",
- X/* 14 */ "Output file write failure",
- X/* 15 */ "Could not create output file",
- X/* 16 */ "Invalid command arguments",
- X/* 17 */ "",
- X/* 18 */ "File not found or no read permission",
- X};
- X#else /* !GLOBALS */
- Xextern char *errors[]; /* Error messages for err() */
- X#endif /* ?GLOBALS */
- END_OF_FILE
- if test 2561 -ne `wc -c <'ziperr.h'`; then
- echo shar: \"'ziperr.h'\" unpacked with wrong size!
- fi
- # end of 'ziperr.h'
- fi
- if test -f 'zipfile.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'zipfile.c'\"
- else
- echo shar: Extracting \"'zipfile.c'\" \(20530 characters\)
- sed "s/^X//" >'zipfile.c' <<'END_OF_FILE'
- X/*
- X
- X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
- X Permission is granted to any individual or institution to use, copy, or
- X redistribute this software so long as all of the original files are included
- X unmodified, that it is not sold for profit, and that this copyright notice
- X is retained.
- X
- X*/
- X
- X/*
- X * zipfile.c by Mark Adler.
- X */
- X
- X#include "zip.h"
- X
- X
- X/* Macros for converting integers in little-endian to machine format */
- X#define SH(a) (((ush)(uch)(a)[0]) | (((ush)(uch)(a)[1]) << 8))
- X#define LG(a) ((ulg)SH(a) | ((ulg)SH((a)+2) << 16))
- X
- X/* Macros for writing machine integers to little-endian format */
- X#define PUTSH(a,f) {putc((char)(a),(f)); putc((char)((a) >> 8),(f));}
- X#define PUTLG(a,f) {PUTSH(a,f) PUTSH((a) >> 16,f)}
- X
- X
- X/* -- Structure of a ZIP file -- */
- X
- X/* Signatures for zip file information headers */
- X#define LOCSIG 0x04034b50L
- X#define CENSIG 0x02014b50L
- X#define ENDSIG 0x06054b50L
- X
- X/* Offsets of values in headers */
- X#define LOCVER 0 /* version needed to extract */
- X#define LOCFLG 2 /* encrypt, implosion flags */
- X#define LOCHOW 4 /* compression method */
- X#define LOCTIM 6 /* last modified file time, DOS format */
- X#define LOCDAT 8 /* last modified file date, DOS format */
- X#define LOCCRC 10 /* uncompressed crc-32 for file */
- X#define LOCSIZ 14 /* compressed size in zip file */
- X#define LOCLEN 18 /* uncompressed size */
- X#define LOCNAM 22 /* length of filename */
- X#define LOCEXT 24 /* length of extra field */
- X
- X#define CENVEM 0 /* version made by */
- X#define CENVER 2 /* version needed to extract */
- X#define CENFLG 4 /* encrypt, implosion flags */
- X#define CENHOW 6 /* compression method */
- X#define CENTIM 8 /* last modified file time, DOS format */
- X#define CENDAT 10 /* last modified file date, DOS format */
- X#define CENCRC 12 /* uncompressed crc-32 for file */
- X#define CENSIZ 16 /* compressed size in zip file */
- X#define CENLEN 20 /* uncompressed size */
- X#define CENNAM 24 /* length of filename */
- X#define CENEXT 26 /* length of extra field */
- X#define CENCOM 28 /* file comment length */
- X#define CENDSK 30 /* disk number start */
- X#define CENATT 32 /* internal file attributes */
- X#define CENATX 34 /* external file attributes */
- X#define CENOFF 38 /* relative offset of local header */
- X
- X#define ENDDSK 0 /* number of this disk */
- X#define ENDBEG 2 /* number of the starting disk */
- X#define ENDSUB 4 /* entries on this disk */
- X#define ENDTOT 6 /* total number of entries */
- X#define ENDSIZ 8 /* size of entire central directory */
- X#define ENDOFF 12 /* offset of central on starting disk */
- X#define ENDCOM 16 /* length of zip file comment */
- X
- X
- X/* Local functions */
- X#ifdef PROTO
- X local int zqcmp(voidp *, voidp *);
- X# ifndef UTIL
- X local int zbcmp(voidp *, voidp far *);
- X local char *cutpath(char *);
- X# endif /* !UTIL */
- X#endif /* PROTO */
- X
- X
- Xlocal int zqcmp(a, b)
- Xvoidp *a, *b; /* pointers to pointers to zip entries */
- X/* Used by qsort() to compare entries in the zfile list. */
- X{
- X return strcmp((*(struct zlist far **)a)->zname,
- X (*(struct zlist far **)b)->zname);
- X}
- X
- X
- X#ifndef UTIL
- X
- Xlocal int zbcmp(n, z)
- Xvoidp *n; /* string to search for */
- Xvoidp far *z; /* pointer to a pointer to a zip entry */
- X/* Used by search() to compare a target to an entry in the zfile list. */
- X{
- X#ifdef OS2
- X return stricmp((char *)n, ((struct zlist far *)z)->zname);
- X#else /* !OS2 */
- X return strcmp((char *)n, ((struct zlist far *)z)->zname);
- X#endif /* ?OS2 */
- X}
- X
- X
- Xstruct zlist far *zsearch(n)
- Xchar *n; /* name to find */
- X/* Return a pointer to the entry in zfile with the name n, or NULL if
- X not found. */
- X{
- X voidp far **p; /* result of search() */
- X
- X if (zcount && (p = search(n, (voidp far **)zsort, zcount, zbcmp)) != NULL)
- X return *(struct zlist far **)p;
- X else
- X return NULL;
- X}
- X
- X#endif /* !UTIL */
- X
- X
- X#ifdef VMS
- X# define PATHCUT ']'
- X#else /* !VMS */
- X# define PATHCUT '/'
- X#endif /* VMS */
- X
- Xchar *ziptyp(s)
- Xchar *s; /* file name to force to zip */
- X/* If the file name *s has a dot (other than the first char), then return
- X the name, otherwise append .zip to the name. Allocate the space for
- X the name in either case. Return a pointer to the new name, or NULL
- X if malloc() fails. */
- X{
- X char *q; /* temporary pointer */
- X char *t; /* pointer to malloc'ed string */
- X
- X if ((t = malloc(strlen(s) + 5)) == NULL)
- X return NULL;
- X strcpy(t, s);
- X#ifdef MSDOS
- X for (q = t; *q; q++)
- X if (*q == '\\')
- X *q = '/';
- X#endif /* MSDOS */
- X if (strrchr((q = strrchr(t, PATHCUT)) == NULL ? t : q + 1, '.') == NULL)
- X strcat(t, ".zip");
- X#ifdef MSDOS
- X#ifndef OS2
- X strupr(t);
- X#endif /* !OS2 */
- X#endif /* MSDOS */
- X return t;
- X}
- X
- X
- Xint readzipfile()
- X/*
- X Make first pass through zip file, reading information from local file
- X headers and then verifying that information with the central file
- X headers. Any deviation from the expected zip file format returns an
- X error. At the end, a sorted list of file names in the zip file is made
- X to facilitate searching by name.
- X
- X The name of the zip file is pointed to by the global "zipfile". The
- X globals zfiles, zcount, zcomlen, zcomment, and zsort are filled in.
- X Return an error code in the ZE_ class.
- X*/
- X{
- X char b[CENHEAD]; /* buffer for central headers */
- X FILE *f; /* zip file */
- X int m; /* mismatch flag */
- X extent n; /* length of name */
- X ulg p; /* current file offset */
- X char r; /* holds reserved bits during memcmp() */
- X ulg s; /* size of data, start of central */
- X char *t; /* temporary variable */
- X char far *u; /* temporary variable */
- X struct zlist far * far *x; /* pointer last entry's link */
- X struct zlist far *z; /* current zip entry structure */
- X
- X /* Initialize zip file info */
- X zipbeg = 0;
- X zfiles = NULL; /* Points to first header */
- X zcomlen = 0; /* zip file comment length */
- X
- X /* If zip file exists, read headers and check structure */
- X if ((f = fopen(zipfile, FOPR)) != NULL)
- X {
- X x = &zfiles; /* first link */
- X p = 0; /* starting file offset */
- X zcount = 0; /* number of files */
- X
- X /* Find start of zip structures */
- X while (fread(b, 4, 1, f) == 1 && (s = LG(b)) != LOCSIG && s != ENDSIG)
- X if (fseek(f, -3L, SEEK_CUR))
- X return ferror(f) ? ZE_READ : ZE_EOF;
- X else
- X p++;
- X zipbeg = p;
- X
- X /* Read local headers */
- X while (LG(b) == LOCSIG)
- X {
- X /* Read local header raw to compare later with central header
- X (this requires that the offest of ext in the zlist structure
- X be greater than or equal to LOCHEAD) */
- X if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL)
- X return ZE_MEM;
- X if (fread(b, LOCHEAD, 1, f) != 1)
- X return ferror(f) ? ZE_READ : ZE_EOF;
- X t = b; u = (char far *)z; n = LOCHEAD;
- X do {
- X *u++ = *t++;
- X } while (--n);
- X
- X /* Link into list */
- X *x = z;
- X z->nxt = NULL;
- X x = &z->nxt;
- X
- X /* Read file name and extra field and skip data */
- X n = SH(LOCNAM + (uch far *)z);
- X z->ext = SH(LOCEXT + (uch far *)z);
- X s = LG(LOCSIZ + (uch far *)z);
- X if (n == 0)
- X {
- X sprintf(errbuf, "%d", zcount + 1);
- X warn("zero-length name for entry #", errbuf);
- X return ZE_FORM;
- X }
- X if ((z->zname = malloc(n+1)) == NULL ||
- X (z->ext && (z->extra = malloc(z->ext)) == NULL))
- X return ZE_MEM;
- X if (fread(z->zname, n, 1, f) != 1 ||
- X (z->ext && fread(z->extra, z->ext, 1, f) != 1) ||
- X fseek(f, (long)s, SEEK_CUR))
- X return ferror(f) ? ZE_READ : ZE_EOF;
- X z->zname[n] = 0; /* terminate name */
- X#ifdef UTIL
- X z->name = z->zname;
- X#else /* !UTIL */
- X z->name = in2ex(z->zname); /* convert to external name */
- X if (z->name == NULL)
- X return ZE_MEM;
- X#endif /* ?UTIL */
- X
- X /* Save offset, update for next header */
- X z->off = p;
- X p += 4 + LOCHEAD + n + z->ext + s;
- X zcount++;
- X
- X /* Read next signature */
- X if (fread(b, 4, 1, f) != 1)
- X return ferror(f) ? ZE_READ : ZE_EOF;
- X }
- X
- X /* Point to start of header list and read central headers */
- X z = zfiles;
- X s = p; /* save start of central */
- X while (LG(b) == CENSIG)
- X {
- X if (z == NULL)
- X {
- X warn("extraneous central header signature", "");
- X return ZE_FORM;
- X }
- X
- X /* Read central header */
- X if (fread(b, CENHEAD, 1, f) != 1)
- X return ferror(f) ? ZE_READ : ZE_EOF;
- X
- X /* Compare local header with that part of central header (except
- X for the reserved bits in the general purpose flags and except
- X for length of extra fields--authentication can make these
- X different in central and local headers) */
- X z->lflg = SH(LOCFLG + (uch far *)z); /* Save reserved bits */
- X r = b[CENFLG+1];
- X ((uch far *)z)[LOCFLG+1] &= 0x1f; /* Zero out reserved bits */
- X b[CENFLG+1] &= 0x1f;
- X for (m = 0, u = (char far *)z, n = 0; n < LOCHEAD - 2; n++)
- X if (u[n] != b[n+2])
- X {
- X if (!m)
- X warn("local and central headers differ for ", z->zname);
- X m = 1;
- X sprintf(errbuf, " offset %d--local = %02x, central = %02x",
- X n, (uch)u[n], (uch)b[n+2]);
- X warn(errbuf, "");
- X }
- X if (m)
- X return ZE_FORM;
- X b[CENFLG+1] = r; /* Restore reserved bits */
- X
- X /* Overwrite local header with translated central header */
- X z->vem = SH(CENVEM + b);
- X z->ver = SH(CENVER + b);
- X z->flg = SH(CENFLG + b); /* may be different from z->lflg */
- X z->how = SH(CENHOW + b);
- X z->tim = LG(CENTIM + b); /* time and date into one long */
- X z->crc = LG(CENCRC + b);
- X z->siz = LG(CENSIZ + b);
- X z->len = LG(CENLEN + b);
- X z->nam = SH(CENNAM + b);
- X z->cext = SH(CENEXT + b); /* may be different from z->ext */
- X z->com = SH(CENCOM + b);
- X z->dsk = SH(CENDSK + b);
- X z->att = SH(CENATT + b);
- X z->atx = LG(CENATX + b);
- X if (z->off != LG(CENOFF + b))
- X {
- X warn("local offset in central header incorrect for ", z->zname);
- X return ZE_FORM;
- X }
- X
- X /* Compare name and extra fields and read comment field */
- X if ((t = malloc(z->nam)) == NULL)
- X return ZE_MEM;
- X if (fread(t, z->nam, 1, f) != 1)
- X {
- X free((voidp *)t);
- X return ferror(f) ? ZE_READ : ZE_EOF;
- X }
- X if (memcmp(t, z->zname, z->nam))
- X {
- X free((voidp *)t);
- X warn("names in local and central differ for ", z->zname);
- X return ZE_FORM;
- X }
- X free((voidp *)t);
- X if (z->cext)
- X {
- X if ((z->cextra = malloc(z->cext)) == NULL)
- X return ZE_MEM;
- X if (fread(z->cextra, z->cext, 1, f) != 1)
- X {
- X free((voidp *)(z->cextra));
- X return ferror(f) ? ZE_READ : ZE_EOF;
- X }
- X if (z->ext == z->cext && memcmp(z->extra, z->cextra, z->ext) == 0)
- X {
- X free((voidp *)(z->cextra));
- X z->cextra = z->extra;
- X }
- X }
- X if (z->com)
- X {
- X if ((z->comment = malloc(z->com)) == NULL)
- X return ZE_MEM;
- X if (fread(z->comment, z->com, 1, f) != 1)
- X {
- X free((voidp *)(z->comment));
- X return ferror(f) ? ZE_READ : ZE_EOF;
- X }
- X }
- X
- X /* Note oddities */
- X if (verbose)
- X {
- X if (z->vem != 10 && z->vem != 11 &&
- X (n = z->vem >> 8) != 3 && n != 2 && n != 6)
- X {
- X sprintf(errbuf, "made by version %d.%d on system type %d: ",
- X (z->vem & 0xff) / 10, (z->vem & 0xff) % 10, z->vem >> 8);
- X warn(errbuf, z->zname);
- X }
- X if (z->ver != 10 && z->ver != 11)
- X {
- X sprintf(errbuf, "needs unzip %d.%d on system type %d: ",
- X (z->ver & 0xff) / 10, (z->ver & 0xff) % 10, z->ver >> 8);
- X warn(errbuf, z->zname);
- X }
- X if (z->flg != z->lflg)
- X {
- X sprintf(errbuf, "local flags = 0x%04x, central = 0x%04x: ",
- X z->lflg, z->flg);
- X warn(errbuf, z->zname);
- X }
- X else if (z->flg & ~7)
- X {
- X sprintf(errbuf, "undefined bits used in flags = 0x%04x: ", z->flg);
- X warn(errbuf, z->zname);
- X }
- X if (z->how > IMPLODE)
- X {
- X sprintf(errbuf, "unknown compression method %u: ", z->how);
- X warn(errbuf, z->zname);
- X }
- X if (z->dsk)
- X {
- X sprintf(errbuf, "starts on disk %u: ", z->dsk);
- X warn(errbuf, z->zname);
- X }
- X if (z->att & ~1)
- X {
- X sprintf(errbuf, "unknown internal attributes = 0x%04x: ", z->att);
- X warn(errbuf, z->zname);
- X }
- X if (((n = z->vem >> 8) != 3) && n != 2 && z->atx & ~0xffL)
- X {
- X sprintf(errbuf, "unknown external attributes = 0x%08lx: ", z->atx);
- X warn(errbuf, z->zname);
- X }
- X if (z->ext || z->cext)
- X if (z->ext == z->cext && z->extra == z->cextra)
- X {
- X sprintf(errbuf, "has %d bytes of extra data: ", z->ext);
- X warn(errbuf, z->zname);
- X }
- X else
- X {
- X sprintf(errbuf,
- X "local extra (%d bytes) != central extra (%d bytes): ",
- X z->ext, z->cext);
- X warn(errbuf, z->zname);
- X }
- X }
- X
- X /* Clear actions */
- X z->mark = 0;
- X z->trash = 0;
- X
- X /* Update file offset */
- X p += 4 + CENHEAD + z->nam + z->cext + z->com;
- X
- X /* Advance to next header structure */
- X z = z->nxt;
- X
- X /* Read next signature */
- X if (fread(b, 4, 1, f) != 1)
- X return ferror(f) ? ZE_READ : ZE_EOF;
- X }
- X
- X /* Read end header */
- X if (z != NULL || LG(b) != ENDSIG)
- X {
- X warn("missing end signature--probably not a zip file (did you", "");
- X warn("remember to use binary mode when you transferred it?)", "");
- X return ZE_FORM;
- X }
- X if (fread(b, ENDHEAD, 1, f) != 1)
- X return ferror(f) ? ZE_READ : ZE_EOF;
- X if (SH(ENDDSK + b) || SH(ENDBEG + b) ||
- X SH(ENDSUB + b) != SH(ENDTOT + b))
- X warn("multiple disk information ignored", "");
- X if (zcount != SH(ENDSUB + b))
- X {
- X warn("count in end of central directory incorrect", "");
- X return ZE_FORM;
- X }
- X if (LG(ENDSIZ + b) != p - s)
- X {
- X warn("central directory size is incorrect", "");
- X return ZE_FORM;
- X }
- X if (LG(ENDOFF + b) != s)
- X {
- X warn("central directory start is incorrect", "");
- X return ZE_FORM;
- X }
- X cenbeg = s;
- X zcomlen = SH(ENDCOM + b);
- X if (zcomlen)
- X {
- X if ((zcomment = malloc(zcomlen)) == NULL)
- X return ZE_MEM;
- X if (fread(zcomment, zcomlen, 1, f) != 1)
- X {
- X free((voidp *)zcomment);
- X return ferror(f) ? ZE_READ : ZE_EOF;
- X }
- X }
- X if (zipbeg)
- X {
- X sprintf(errbuf, " has a preamble of %ld bytes", zipbeg);
- X warn(zipfile, errbuf);
- X }
- X if (getc(f) != EOF)
- X warn("garbage at end of zip file ignored", "");
- X
- X /* Done with zip file for now */
- X fclose(f);
- X
- X /* If one or more files, sort by name */
- X if (zcount)
- X {
- X if ((x = zsort =
- X (struct zlist far **)malloc(zcount * sizeof(struct zlist far *))) ==
- X NULL)
- X return ZE_MEM;
- X for (z = zfiles; z != NULL; z = z->nxt)
- X *x++ = z;
- X qsort((char *)zsort, zcount, sizeof(struct zlist far *), zqcmp);
- X }
- X }
- X return ZE_OK;
- X}
- X
- X
- Xint putlocal(z, f)
- Xstruct zlist far *z; /* zip entry to write local header for */
- XFILE *f; /* file to write to */
- X/* Write a local header described by *z to file *f. Return an error code
- X in the ZE_ class. */
- X{
- X PUTLG(LOCSIG, f);
- X PUTSH(z->ver, f);
- X PUTSH(z->lflg, f);
- X PUTSH(z->how, f);
- X PUTLG(z->tim, f);
- X PUTLG(z->crc, f);
- X PUTLG(z->siz, f);
- X PUTLG(z->len, f);
- X PUTSH(z->nam, f);
- X PUTSH(z->ext, f);
- X if (fwrite(z->zname, 1, z->nam, f) != z->nam ||
- X z->ext && fwrite(z->extra, 1, z->ext, f) != z->ext)
- X return ZE_TEMP;
- X return ZE_OK;
- X}
- X
- X
- Xint putcentral(z, f)
- Xstruct zlist far *z; /* zip entry to write central header for */
- XFILE *f; /* file to write to */
- X/* Write a central header described by *z to file *f. Return an error code
- X in the ZE_ class. */
- X{
- X PUTLG(CENSIG, f);
- X PUTSH(z->vem, f);
- X PUTSH(z->ver, f);
- X PUTSH(z->flg, f);
- X PUTSH(z->how, f);
- X PUTLG(z->tim, f);
- X PUTLG(z->crc, f);
- X PUTLG(z->siz, f);
- X PUTLG(z->len, f);
- X PUTSH(z->nam, f);
- X PUTSH(z->cext, f);
- X PUTSH(z->com, f);
- X PUTSH(z->dsk, f);
- X PUTSH(z->att, f);
- X PUTLG(z->atx, f);
- X PUTLG(z->off, f);
- X if (fwrite(z->zname, 1, z->nam, f) != z->nam ||
- X z->cext && fwrite(z->cextra, 1, z->cext, f) != z->cext ||
- X z->com && fwrite(z->comment, 1, z->com, f) != z->com)
- X return ZE_TEMP;
- X return ZE_OK;
- X}
- X
- X
- Xint putend(n, s, c, m, z, f)
- Xint n; /* number of entries in central directory */
- Xulg s, c; /* size and offset of central directory */
- Xextent m; /* length of zip file comment (0 if none) */
- Xchar *z; /* zip file comment if m != 0 */
- XFILE *f; /* file to write to */
- X/* Write the end of central directory data to file *f. Return an error code
- X in the ZE_ class. */
- X{
- X PUTLG(ENDSIG, f);
- X PUTSH(0, f);
- X PUTSH(0, f);
- X PUTSH(n, f);
- X PUTSH(n, f);
- X PUTLG(s, f);
- X PUTLG(c, f);
- X PUTSH(m, f);
- X if (m && fwrite(z, 1, m, f) != m)
- X return ZE_TEMP;
- X return ZE_OK;
- X}
- X
- X
- X#ifndef UTIL
- X
- Xlocal char *cutpath(p)
- Xchar *p; /* path string */
- X/* Cut the last path component off the name *p in place. Return p. */
- X{
- X char *r; /* pointer to last path delimiter */
- X
- X#ifdef VMS /* change [w.x.y]z to [w.x]y.DIR */
- X if ((r = strrchr(p, ']')) != NULL)
- X {
- X *r = 0;
- X if ((r = strrchr(p, '.')) != NULL)
- X {
- X *r = ']';
- X strcat(r, ".DIR"); /* this assumes a little padding--see PAD */
- X }
- X else
- X *p = 0;
- X }
- X else
- X *p = 0;
- X#else /* !VMS */ /* change w/x/y/z to w/x/y */
- X if ((r = strrchr(p, '/')) != NULL)
- X *r = 0;
- X else
- X *p = 0;
- X#endif /* ?VMS */
- X return p;
- X}
- X
- X
- Xint trash()
- X/* Delete the compressed files and the directories that contained the deleted
- X files, if empty. Return an error code in the ZE_ class. Failure of
- X destroy() or deletedir() is ignored. */
- X{
- X extent i; /* counter on deleted names */
- X extent k; /* number of deleted directories this pass */
- X extent n; /* number of deleted names left to handle */
- X struct zlist far **s; /* table of zip entries to handle, sorted */
- X struct zlist far *z; /* current zip entry */
- X
- X /* Count and delete marked names */
- X n = 0;
- X for (z = zfiles; z != NULL; z = z->nxt)
- X if (z->mark || z->trash)
- X {
- X z->mark = 1;
- X n++;
- X if (verbose)
- X printf("zip diagnostic: trashing file %s\n", z->name);
- X destroy(z->name);
- X }
- X
- X /* Try to delete all paths that lead up to marked names */
- X if (n)
- X {
- X if ((s = (struct zlist far **)malloc((n+1)*sizeof(struct zlist far *))) ==
- X NULL ||
- X (s[0] = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL)
- X return ZE_MEM;
- X s[0]->name = "";
- X s++;
- X do {
- X n = k = 0;
- X for (z = zfiles; z != NULL; z = z->nxt)
- X if (z->mark)
- X s[n++] = z;
- X qsort((char *)s, n, sizeof(struct zlist far *), zqcmp);
- X for (i = 0; i < n; i++)
- X if (*cutpath(s[i]->name) && strcmp(s[i]->name, s[i-1]->name))
- X {
- X if (verbose)
- X printf("zip diagnostic: trashing directory %s\n", s[i]->name);
- X deletedir(s[i]->name);
- X k++;
- X }
- X else
- X s[i]->mark = 0;
- X } while (k);
- X farfree((voidp far *)((--s)[0]));
- X free((voidp *)s);
- X }
- X return ZE_OK;
- X}
- X
- X#endif /* !UTIL */
- END_OF_FILE
- if test 20530 -ne `wc -c <'zipfile.c'`; then
- echo shar: \"'zipfile.c'\" unpacked with wrong size!
- fi
- # end of 'zipfile.c'
- fi
- if test -f 'zipsplit.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'zipsplit.c'\"
- else
- echo shar: Extracting \"'zipsplit.c'\" \(16863 characters\)
- sed "s/^X//" >'zipsplit.c' <<'END_OF_FILE'
- X/*
- X
- X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
- X Permission is granted to any individual or institution to use, copy, or
- X redistribute this software so long as all of the original files are included
- X unmodified, that it is not sold for profit, and that this copyright notice
- X is retained.
- X
- X*/
- X
- X/*
- X * zipsplit.c by Mark Adler.
- X */
- X
- X#define UTIL
- X#include "revision.h"
- X#include "zip.h"
- X#include <signal.h>
- X
- X#define DEFSIZ 36000L /* Default split size (change in help() too) */
- X#ifdef MSDOS
- X# define NL 2 /* Number of bytes written for a \n */
- X#else /* !MSDOS */
- X# define NL 1 /* Number of bytes written for a \n */
- X#endif /* ?MSDOS */
- X#define INDEX "zipsplit.idx" /* Name of index file */
- X
- X
- X/* Local functions */
- X#ifdef PROTO
- X local void err(int, char *);
- X local void handler(int);
- X local void license(void);
- X local void help(void);
- X local extent simple(ulg *, extent, ulg, ulg);
- X local int descmp(voidp *, voidp *);
- X local extent greedy(ulg *, extent, ulg, ulg);
- X void main(int, char **);
- X#endif /* PROTO */
- X
- X
- X/* Output zip files */
- Xlocal char template[16]; /* name template for output files */
- Xlocal int zipsmade = 0; /* number of zip files made */
- Xlocal int indexmade = 0; /* true if index file made */
- Xlocal char *path = NULL; /* space for full name */
- Xlocal char *name; /* where name goes in path[] */
- X
- X
- Xlocal void err(c, h)
- Xint c; /* error code from the ZE_ class */
- Xchar *h; /* message about how it happened */
- X/* Issue a message for the error, clean up files and memory, and exit. */
- X{
- X if (PERR(c))
- X perror("zipsplit error");
- X fprintf(stderr, "zipsplit error: %s (%s)\n", errors[c-1], h);
- X if (indexmade)
- X {
- X strcpy(name, INDEX);
- X destroy(path);
- X }
- X for (; zipsmade; zipsmade--)
- X {
- X sprintf(name, template, zipsmade);
- X destroy(path);
- X }
- X if (path != NULL)
- X free((voidp *)path);
- X if (zipfile != NULL)
- X free((voidp *)zipfile);
- X#ifdef VMS
- X exit(0);
- X#else /* !VMS */
- X exit(c);
- X#endif /* ?VMS */
- X}
- X
- X
- X
- Xlocal void handler(s)
- Xint s; /* signal number (ignored) */
- X/* Upon getting a user interrupt, abort cleanly using err(). */
- X{
- X#ifndef MSDOS
- X putc('\n', stderr);
- X#endif /* !MSDOS */
- X err(ZE_ABORT, "aborting");
- X s++; /* keep some compilers happy */
- X}
- X
- X
- Xvoid warn(a, b)
- Xchar *a, *b; /* message strings juxtaposed in output */
- X/* Print a warning message to stderr and return. */
- X{
- X fprintf(stderr, "zipsplit warning: %s%s\n", a, b);
- X}
- X
- X
- Xlocal void license()
- X/* Print license information to stdout. */
- X{
- X extent i; /* counter for copyright array */
- X
- X for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
- X puts(copyright[i]);
- X for (i = 0; i < sizeof(disclaimer)/sizeof(char *); i++)
- X puts(disclaimer[i]);
- X}
- X
- X
- Xlocal void help()
- X/* Print help (along with license info) to stdout. */
- X{
- X extent i; /* counter for help array */
- X
- X /* help array */
- X static char *text[] = {
- X"",
- X"ZipSplit %d.%d (%s)",
- X"Usage: zipsplit [-ti] [-n size] [-b path] zipfile",
- X" -t report how many files it will take, but don't make them",
- X" -i make index (zipsplit.idx) and count its size against first zip file",
- X" -n make zip files no larger than \"size\" (default = 36000)",
- X" -b use \"path\" for the output zip files",
- X" -s do a sequential split even if it takes more zip files",
- X" -h show this help -l show software license"
- X };
- X
- X for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
- X puts(copyright[i]);
- X for (i = 0; i < sizeof(text)/sizeof(char *); i++)
- X {
- X printf(text[i], REVISION / 10, REVISION % 10, REVDATE);
- X putchar('\n');
- X }
- X}
- X
- X
- Xlocal extent simple(a, n, c, d)
- Xulg *a; /* items to put in bins, return value: destination bins */
- Xextent n; /* number of items */
- Xulg c; /* capacity of each bin */
- Xulg d; /* amount to deduct from first bin */
- X/* Return the number of bins of capacity c that are needed to contain the
- X integers in a[0..n-1] placed sequentially into the bins. The value d
- X is deducted initially from the first bin (space for index). The entries
- X in a[] are replaced by the destination bins. */
- X{
- X extent k; /* current bin number */
- X ulg t; /* space used in current bin */
- X
- X t = k = 0;
- X while (n--)
- X {
- X if (*a + t > c - (k == 0 ? d : 0))
- X {
- X k++;
- X t = 0;
- X }
- X t += *a;
- X *(ulg huge *)a++ = k;
- X }
- X return k + 1;
- X}
- X
- X
- Xlocal int descmp(a, b)
- Xvoidp *a, *b; /* pointers to pointers to ulg's to compare */
- X/* Used by qsort() in greedy() to do a descending sort. */
- X{
- X return **(ulg **)a < **(ulg **)b ? 1 : (**(ulg **)a > **(ulg **)b ? -1 : 0);
- X}
- X
- X
- Xlocal extent greedy(a, n, c, d)
- Xulg *a; /* items to put in bins, return value: destination bins */
- Xextent n; /* number of items */
- Xulg c; /* capacity of each bin */
- Xulg d; /* amount to deduct from first bin */
- X/* Return the number of bins of capacity c that are needed to contain the
- X items with sizes a[0..n-1] placed non-sequentially into the bins. The
- X value d is deducted initially from the first bin (space for index).
- X The entries in a[] are replaced by the destination bins. */
- X{
- X ulg *b; /* space left in each bin (malloc'ed for each m) */
- X ulg *e; /* copy of argument a[] (malloc'ed) */
- X extent i; /* steps through items */
- X extent j; /* steps through bins */
- X extent k; /* best bin to put current item in */
- X extent m; /* current number of bins */
- X ulg **s; /* pointers to e[], sorted descending (malloc'ed) */
- X ulg t; /* space left in best bin (index k) */
- X
- X /* Algorithm:
- X 1. Copy a[] to e[] and sort pointers to e[0..n-1] (in s[]), in
- X descending order.
- X 2. Compute total of s[] and set m to the smallest number of bins of
- X capacity c that can hold the total.
- X 3. Allocate m bins.
- X 4. For each item in s[], starting with the largest, put it in the
- X bin with the smallest current capacity greater than or equal to the
- X item's size. If no bin has enough room, increment m and go to step 4.
- X 5. Else, all items ended up in a bin--return m.
- X */
- X
- X /* Copy a[] to e[], put pointers to e[] in s[], and sort s[]. Also compute
- X the initial number of bins (minus 1). */
- X if ((e = (ulg *)malloc(n * sizeof(ulg))) == NULL ||
- X (s = (ulg **)malloc(n * sizeof(ulg *))) == NULL)
- X {
- X if (e != NULL)
- X free((voidp *)e);
- X err(ZE_MEM, "was trying a smart split");
- X return 0; /* only to make compiler happy */
- X }
- X memcpy((char *)e, (char *)a, n * sizeof(ulg));
- X for (t = i = 0; i < n; i++)
- X t += *(s[i] = e + i);
- X m = (extent)((t + c - 1) / c) - 1; /* pre-decrement for loop */
- X qsort((char *)s, n, sizeof(ulg *), descmp);
- X
- X /* Stuff bins until successful */
- X do {
- X /* Increment the number of bins, allocate and initialize bins */
- X if ((b = (ulg *)malloc(++m * sizeof(ulg))) == NULL)
- X {
- X free((voidp *)s);
- X free((voidp *)e);
- X err(ZE_MEM, "was trying a smart split");
- X }
- X b[0] = c - d; /* leave space in first bin */
- X for (j = 1; j < m; j++)
- X b[j] = c;
- X
- X /* Fill the bins greedily */
- X for (i = 0; i < n; i++)
- X {
- X /* Find smallest bin that will hold item i (size s[i]) */
- X t = c + 1;
- X for (k = j = 0; j < m; j++)
- X if (*s[i] <= b[j] && b[j] < t)
- X t = b[k = j];
- X
- X /* If no bins big enough for *s[i], try next m */
- X if (t == c + 1)
- X break;
- X
- X /* Diminish that bin and save where it goes */
- X b[k] -= *s[i];
- X a[(int)((ulg huge *)(s[i]) - (ulg huge *)e)] = k;
- X }
- X
- X /* Clean up */
- X free((voidp *)b);
- X
- X /* Do until all items put in a bin */
- X } while (i < n);
- X
- X /* Done--clean up and return the number of bins needed */
- X free((voidp *)s);
- X free((voidp *)e);
- X return m;
- X}
- X
- X
- Xvoid main(argc, argv)
- Xint argc; /* number of tokens in command line */
- Xchar **argv; /* command line tokens */
- X/* Split a zip file into several zip files less than a specified size. See
- X the command help in help() above. */
- X{
- X ulg *a; /* malloc'ed list of sizes, dest bins */
- X extent *b; /* heads of bin linked lists (malloc'ed) */
- X ulg c; /* bin capacity, start of central directory */
- X int d; /* if true, just report the number of disks */
- X FILE *e; /* input zip file */
- X FILE *f; /* output index and zip files */
- X extent g; /* number of bins from greedy(), entry to write */
- X int h; /* how to split--true means simple split, counter */
- X ulg i; /* size of index file or zero if none */
- X extent j; /* steps through zip entries, bins */
- X int k; /* next argument type */
- X ulg *p; /* malloc'ed list of sizes, dest bins for greedy() */
- X char *q; /* steps through option characters */
- X int r; /* temporary variable, counter */
- X extent s; /* number of bins needed */
- X ulg t; /* total of sizes, end of central directory */
- X struct zlist far **w; /* malloc'ed table for zfiles linked list */
- X int x; /* if true, make an index file */
- X struct zlist far *z; /* steps through zfiles linked list */
- X
- X
- X /* If no args, show help */
- X if (argc == 1)
- X {
- X help();
- X exit(0);
- X }
- X
- X /* Go through args */
- X signal(SIGINT, handler);
- X signal(SIGTERM, handler);
- X k = h = x = d = 0;
- X c = DEFSIZ;
- X for (r = 1; r < argc; r++)
- X if (*argv[r] == '-')
- X if (argv[r][1])
- X for (q = argv[r]+1; *q; q++)
- X switch(*q)
- X {
- X case 'b': /* Specify path for output files */
- X if (k)
- X err(ZE_PARMS, "options are separate and precede zip file");
- X else
- X k = 1; /* Next non-option is path */
- X break;
- X case 'h': /* Show help */
- X help(); exit(0);
- X case 'i': /* Make an index file */
- X x = 1;
- X break;
- X case 'l': /* Show copyright and disclaimer */
- X license(); exit(0);
- X case 'n': /* Specify maximum size of resulting zip files */
- X if (k)
- X err(ZE_PARMS, "options are separate and precede zip file");
- X else
- X k = 2; /* Next non-option is size */
- X break;
- X case 's':
- X h = 1; /* Only try simple */
- X break;
- X case 't': /* Just report number of disks */
- X d = 1;
- X break;
- X default:
- X err(ZE_PARMS, "unknown option");
- X }
- X else
- X err(ZE_PARMS, "zip file cannot be stdin");
- X else
- X if (k == 0)
- X if (zipfile == NULL)
- X {
- X if ((zipfile = ziptyp(argv[r])) == NULL)
- X err(ZE_MEM, "was processing arguments");
- X }
- X else
- X err(ZE_PARMS, "can only specify one zip file");
- X else if (k == 1)
- X {
- X tempath = argv[r];
- X k = 0;
- X }
- X else /* k must be 2 */
- X {
- X if ((c = (ulg)atol(argv[r])) < 100) /* 100 is smallest zip file */
- X err(ZE_PARMS, "invalid size given");
- X k = 0;
- X }
- X if (zipfile == NULL)
- X err(ZE_PARMS, "need to specify zip file");
- X
- X
- X /* Read zip file */
- X if ((r = readzipfile()) != ZE_OK)
- X err(r, zipfile);
- X if (zfiles == NULL)
- X err(ZE_NAME, zipfile);
- X
- X /* Make a list of sizes and check against capacity. Also compute the
- X size of the index file. */
- X c -= ENDHEAD + 4; /* subtract overhead/zipfile */
- X if ((a = (ulg *)malloc(zcount * sizeof(ulg))) == NULL ||
- X (w = (struct zlist far **)malloc(zcount * sizeof(struct zlist far *))) ==
- X NULL)
- X {
- X if (a != NULL)
- X free((voidp *)a);
- X err(ZE_MEM, "was computing split");
- X return;
- X }
- X i = t = 0;
- X for (j = 0, z = zfiles; j < zcount; j++, z = z->nxt)
- X {
- X w[j] = z;
- X if (x)
- X i += z->nam + 6 + NL;
- X t += a[j] = 8 + LOCHEAD + CENHEAD +
- X 2 * (ulg)z->nam + 2 * (ulg)z->ext + z->com + z->siz;
- X if (a[j] > c)
- X {
- X free((voidp *)w); free((voidp *)a);
- X err(ZE_BIG, z->zname);
- X }
- X }
- X
- X /* Decide on split to use, report number of files */
- X if (h)
- X s = simple(a, zcount, c, i);
- X else
- X {
- X if ((p = (ulg *)malloc(zcount * sizeof(ulg))) == NULL)
- X {
- X free((voidp *)w); free((voidp *)a);
- X err(ZE_MEM, "was computing split");
- X }
- X memcpy((char *)p, (char *)a, zcount * sizeof(ulg));
- X s = simple(a, zcount, c, i);
- X g = greedy(p, zcount, c, i);
- X if (s <= g)
- X free((voidp *)p);
- X else
- X {
- X free((voidp *)a);
- X a = p;
- X s = g;
- X }
- X }
- X printf("%d zip files w%s be made (%d%% efficiency)\n",
- X s, d ? "ould" : "ill", ((200 * ((t + c - 1)/c)) / s + 1) >> 1);
- X if (d)
- X {
- X free((voidp *)w); free((voidp *)a);
- X free((voidp *)zipfile);
- X zipfile = NULL;
- X return;
- X }
- X
- X /* Set up path for output files */
- X if ((path = malloc(tempath == NULL ? 13 : strlen(tempath) + 14)) == NULL)
- X err(ZE_MEM, "was making output file names");
- X if (tempath == NULL)
- X name = path;
- X else
- X {
- X strcpy(path, tempath);
- X if (path[0] && path[strlen(path) - 1] != '/')
- X strcat(path, "/");
- X name = path + strlen(path);
- X }
- X
- X /* Write the index file */
- X if (x)
- X {
- X strcpy(name, INDEX);
- X printf("creating %s\n", path);
- X indexmade = 1;
- X if ((f = fopen(path, "w")) == NULL)
- X {
- X free((voidp *)w); free((voidp *)a);
- X err(ZE_CREAT, path);
- X }
- X for (j = 0; j < zcount; j++)
- X fprintf(f, "%5ld %s\n", a[j] + 1, w[j]->zname);
- X if ((j = ferror(f)) != 0 || fclose(f))
- X {
- X if (j)
- X fclose(f);
- X free((voidp *)w); free((voidp *)a);
- X err(ZE_WRITE, path);
- X }
- X }
- X
- X /* Make linked lists of results */
- X if ((b = (extent *)malloc(s * sizeof(extent))) == NULL)
- X {
- X free((voidp *)w); free((voidp *)a);
- X err(ZE_MEM, "was computing split");
- X }
- X for (j = 0; j < s; j++)
- X b[j] = -1;
- X j = zcount;
- X while (j--)
- X {
- X g = (extent)a[j];
- X a[j] = b[g];
- X b[g] = j;
- X }
- X
- X /* Make a name template for the zip files that is eight or less characters
- X before the .zip, and that will not overwrite the original zip file. */
- X for (k = 1, j = s; j >= 10; j /= 10)
- X k++;
- X if (k > 7)
- X {
- X free((voidp *)b); free((voidp *)w); free((voidp *)a);
- X err(ZE_PARMS, "way too many zip files must be made");
- X }
- X if ((q = strrchr(zipfile, '/')) != NULL)
- X q++;
- X else
- X q = zipfile;
- X r = 0;
- X while ((g = *q++) != 0 && g != '.' && r < 8 - k)
- X template[r++] = (char)g;
- X if (r == 0)
- X template[r++] = '_';
- X else if (g >= '0' && g <= '9')
- X template[r - 1] = (char)(template[r - 1] == '_' ? '-' : '_');
- X sprintf(template + r, "%%0%dd.zip", k);
- X
- X /* Make the zip files from the linked lists of entry numbers */
- X if ((e = fopen(zipfile, FOPR)) == NULL)
- X {
- X free((voidp *)b); free((voidp *)w); free((voidp *)a);
- X err(ZE_NAME, zipfile);
- X }
- X free((voidp *)zipfile);
- X zipfile = NULL;
- X for (j = 0; j < s; j++)
- X {
- X sprintf(name, template, j + 1);
- X printf("creating %s\n", path);
- X zipsmade = j + 1;
- X if ((f = fopen(path, FOPW)) == NULL)
- X {
- X free((voidp *)b); free((voidp *)w); free((voidp *)a);
- X err(ZE_CREAT, path);
- X }
- X for (g = b[j]; g != (extent)-1; g = (extent)a[g])
- X {
- X if (fseek(e, w[g]->off, SEEK_SET))
- X {
- X free((voidp *)b); free((voidp *)w); free((voidp *)a);
- X err(ferror(e) ? ZE_READ : ZE_EOF, zipfile);
- X }
- X if ((r = zipcopy(w[g], e, f)) != ZE_OK)
- X {
- X free((voidp *)b); free((voidp *)w); free((voidp *)a);
- X if (r == ZE_TEMP)
- X err(ZE_WRITE, path);
- X else
- X err(r, zipfile);
- X }
- X }
- X if ((c = ftell(f)) == -1L)
- X {
- X free((voidp *)b); free((voidp *)w); free((voidp *)a);
- X err(ZE_WRITE, path);
- X }
- X for (g = b[j], k = 0; g != (extent)-1; g = (extent)a[g], k++)
- X if ((r = putcentral(w[g], f)) != ZE_OK)
- X {
- X free((voidp *)b); free((voidp *)w); free((voidp *)a);
- X err(ZE_WRITE, path);
- X }
- X if ((t = ftell(f)) == -1L)
- X {
- X free((voidp *)b); free((voidp *)w); free((voidp *)a);
- X err(ZE_WRITE, path);
- X }
- X if ((r = putend(k, t - c, c, (extent)0, (char *)NULL, f)) != ZE_OK)
- X {
- X free((voidp *)b); free((voidp *)w); free((voidp *)a);
- X err(ZE_WRITE, path);
- X }
- X if (ferror(f) || fclose(f))
- X {
- X free((voidp *)b); free((voidp *)w); free((voidp *)a);
- X err(ZE_WRITE, path);
- X }
- X }
- X free((voidp *)b); free((voidp *)w); free((voidp *)a);
- X fclose(e);
- X
- X /* Done! */
- X exit(0);
- X}
- END_OF_FILE
- if test 16863 -ne `wc -c <'zipsplit.c'`; then
- echo shar: \"'zipsplit.c'\" unpacked with wrong size!
- fi
- # end of 'zipsplit.c'
- fi
- if test -f 'zipup.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'zipup.c'\"
- else
- echo shar: Extracting \"'zipup.c'\" \(10409 characters\)
- sed "s/^X//" >'zipup.c' <<'END_OF_FILE'
- X/*
- X
- X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
- X Permission is granted to any individual or institution to use, copy, or
- X redistribute this software so long as all of the original files are included
- X unmodified, that it is not sold for profit, and that this copyright notice
- X is retained.
- X
- X*/
- X
- X/*
- X * zipup.c by Mark Adler.
- X */
- X
- X#define NOCPYRT /* this is not a main module */
- X#include "zip.h"
- X#include "revision.h"
- X
- X/* Use the raw functions for MSDOS and Unix to save on buffer space.
- X They're not used for VMS since it doesn't work (raw is weird on VMS).
- X (This sort of stuff belongs in fileio.c, but oh well.) */
- X#ifdef VMS
- X typedef FILE *ftype;
- X# define fhow FOPR
- X# define fbad NULL
- X# define zopen(n,p) fopen(n,p)
- X# define zread(f,b,n) fread(b,1,n,f)
- X# define zclose(f) fclose(f)
- X# define zerr(f) ferror(f)
- X# define zrew(f) rewind(f)
- X#else /* !VMS */
- X# ifdef MSDOS
- X# include <io.h>
- X# include <fcntl.h>
- X# define fhow (O_RDONLY|O_BINARY)
- X# else /* !MSDOS */
- X int open OF((char *, int));
- X int read OF((int, char *, int));
- X int close OF((int));
- X int lseek OF((int,long,int));
- X# define fhow 0
- X# endif /* ?MSDOS */
- X typedef int ftype;
- X# define fbad (-1)
- X# define zopen(n,p) open(n,p)
- X# define zread(f,b,n) read(f,b,n)
- X# define zclose(f) close(f)
- X# define zerr(f) (k<0)
- X# define zrew(f) lseek(f,0L,0)
- X#endif /* ?VMS */
- X
- X
- X/* Local functions */
- X#ifdef PROTO
- X# ifndef UTIL
- X local int suffixes(char *, char *);
- X# endif /* !UTIL */
- X#endif /* PROTO */
- X
- X
- X/* Note: a zip "entry" includes a local header (which includes the file
- X name), an encryption header if encrypting, and the compressed data. */
- X
- X
- Xint zipcopy(z, x, y)
- Xstruct zlist far *z; /* zip entry to copy */
- XFILE *x, *y; /* source and destination files */
- X/* Copy the zip entry described by *z from file *x to file *y. Return an
- X error code in the ZE_ class. */
- X{
- X ulg n; /* holds local header offset */
- X
- X if (fseek(x, z->off, SEEK_SET))
- X return ferror(x) ? ZE_READ : ZE_EOF;
- X if ((n = ftell(y)) == -1L)
- X return ZE_TEMP;
- X z->off = n;
- X n = 4 + LOCHEAD + (long)z->nam + (long)z->ext + z->siz;
- X return fcopy(x, y, n);
- X}
- X
- X
- X#ifndef UTIL
- X
- Xint percent(n, m)
- Xulg n, m; /* n is the original size, m is the new size */
- X/* Return the percentage compression from n to m using only integer
- X operations */
- X{
- X if (n > 0xffffffL) /* If n >= 16M */
- X { /* then divide n and m by 256 */
- X n += 0x80; n >>= 8;
- X m += 0x80; m >>= 8;
- X }
- X return n ? (int)(1 + (200 * (n - m))/n) >> 1 : 0;
- X}
- X
- X
- Xlocal int suffixes(a, s)
- Xchar *a; /* name to check suffix of */
- Xchar *s; /* list of suffixes separated by : or ; */
- X/* Return true if a ends in any of the suffixes in the list s. */
- X{
- X int m; /* true if suffix matches so far */
- X char *p; /* pointer into special */
- X char *q; /* pointer into name a */
- X
- X m = 1;
- X q = a + strlen(a) - 1;
- X for (p = s + strlen(s) - 1; p >= s; p--)
- X if (*p == ':' || *p == ';')
- X if (m)
- X return 1;
- X else
- X {
- X m = 1;
- X q = a + strlen(a) - 1;
- X }
- X else
- X#ifdef OS2
- X {
- X m = m && q >= a && tolower(*p) == tolower(*q);
- X q--;
- X }
- X#else /* !OS2 */
- X m = m && q >= a && *p == *q--;
- X#endif /* ?OS2 */
- X return m;
- X}
- X
- X
- Xint zipup(z, y)
- Xstruct zlist far *z; /* zip entry to compress */
- XFILE *y; /* output file */
- X/* Compress the file z->name into the zip entry described by *z and write
- X it to the file *y. Determine the best method (store, shrink, or implode)
- X and use it. Encrypt if requested. Return an error code in the
- X ZE_ class. */
- X{
- X ulg a; /* attributes returned by filetime() */
- X char *b; /* malloc'ed file buffer */
- X ulg c; /* crc on uncompressed file data */
- X ftype f; /* file to compress */
- X uch g; /* flags returned by implode */
- X int h; /* compression method chosen (how) */
- X#ifndef NOIMPLODE
- X ulg i; /* size of imploded data */
- X#endif /* !NOIMPLODE */
- X extent k; /* result of zread */
- X int l; /* true if this file is a symbolic link */
- X int m; /* method for this entry */
- X ulg n; /* size of uncompressed file */
- X long q; /* size returned by filetime */
- X int r; /* temporary variable */
- X ulg s; /* size of shrunk or compressed data */
- X
- X /* Open file to zip up */
- X if ((z->tim = filetime(z->name, &a, &q)) == 0 || q < 0)
- X return ZE_OPEN;
- X l = issymlnk(a);
- X if (l)
- X f = fbad;
- X else if ((f = zopen(z->name, fhow)) == fbad)
- X return ZE_OPEN;
- X
- X /* Select method based on the suffix and the global method */
- X m = special != NULL && suffixes(z->name, special) ? STORE : method;
- X
- X /* Don't bother with shrink for "large" files (320 is what PKZIP uses--the
- X number used here must be <= BSZ) */
- X if (m == BEST && q > 512)
- X m = IMPLODE;
- X if (q == 0)
- X m = STORE;
- X
- X /* Make first pass on the file, computing the crc and length, and running
- X shrink and implode on it. */
- X n = 0;
- X c = updcrc((char *)NULL, 0);
- X if ((b = malloc(BSZ)) == NULL)
- X return ZE_MEM;
- X if (m == BEST || m == SHRINK)
- X if ((r = shr_setup()) != ZE_OK)
- X return r;
- X else
- X shract = 1;
- X while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
- X {
- X n += k;
- X c = updcrc(b, k);
- X#ifdef MINIX
- X if (l)
- X q = k;
- X#endif /* MINIX */
- X if ((m == BEST || m == SHRINK) && (r = shr_p1((uch *)b, k)) != ZE_OK)
- X {
- X free((voidp *)b);
- X shr_clear();
- X shract = 0;
- X return r;
- X }
- X if (m == BEST) /* free up shrink data structures */
- X {
- X if ((!l && zread(f, b, BSZ) != 0)
- X#ifndef VMS
- X || n != (ulg)q
- X#endif /* !VMS */
- X )
- X return ZE_READ;
- X if ((r = shr_size(&s)) != ZE_OK)
- X {
- X shr_clear();
- X shract = 0;
- X return r;
- X }
- X }
- X#ifndef NOIMPLODE
- X if (m == BEST || m == IMPLODE)
- X {
- X if (!impact)
- X if ((r = imp_setup(q, level)) != ZE_OK)
- X return r;
- X else
- X impact = 1;
- X if ((r = imp_p1(b, k)) != ZE_OK)
- X {
- X free((voidp *)b);
- X imp_clear();
- X impact = 0;
- X return r;
- X }
- X }
- X#endif /* !NOIMPLODE */
- X if (m == BEST || l)
- X break;
- X }
- X free((voidp *)b);
- X if (!l && zerr(f))
- X return ZE_READ;
- X
- X /* Determine the best method to use */
- X g = 0;
- X if (noisy && verbose)
- X printf(" (n=%lu)", n);
- X if (m == SHRINK && (r = shr_size(&s)) != ZE_OK)
- X {
- X shr_clear();
- X shract = 0;
- X return r;
- X }
- X if (noisy && verbose && (m == BEST || m == SHRINK))
- X printf(" (s=%lu)", s);
- X#ifndef NOIMPLODE
- X if ((m == BEST || m == IMPLODE) && (r = imp_size(&i, &g)) != ZE_OK)
- X {
- X imp_clear();
- X impact = 0;
- X return r;
- X }
- X if (noisy && verbose && (m == BEST || m == IMPLODE))
- X printf(" (i=%lu)", i);
- X if ((m == BEST || m == IMPLODE) && i < n && (m == IMPLODE || i < s))
- X {
- X if (noisy)
- X {
- X printf(" (imploded %d%%)", percent(n, i));
- X fflush(stdout);
- X }
- X h = IMPLODE;
- X s = i;
- X if (m == BEST)
- X {
- X shr_clear();
- X shract = 0;
- X }
- X if (!l)
- X zclose(f);
- X }
- X else
- X#endif /* !NOIMPLODE */
- X if ((m == BEST || m == SHRINK) && s < n)
- X {
- X if (noisy)
- X {
- X printf(" (shrunk %d%%)", percent(n, s));
- X fflush(stdout);
- X }
- X h = SHRINK;
- X#ifndef NOIMPLODE
- X if (m == BEST)
- X {
- X imp_clear();
- X impact = 0;
- X }
- X#endif /* !NOIMPLODE */
- X if (!l)
- X zclose(f);
- X }
- X else
- X {
- X if (noisy)
- X {
- X printf(" (stored 0%%)");
- X fflush(stdout);
- X }
- X h = STORE;
- X s = n;
- X#ifndef NOIMPLODE
- X if (m == BEST || m == IMPLODE)
- X {
- X imp_clear();
- X impact = 0;
- X }
- X#endif /* !NOIMPLODE */
- X if (m == BEST || m == SHRINK)
- X {
- X shr_clear();
- X shract = 0;
- X }
- X }
- X
- X#ifndef VMS
- X /* Check size (but not in VMS--variable record lengths mess it up) */
- X if (n != (ulg)q)
- X return ZE_READ;
- X#endif /* !VMS */
- X
- X /* Fill in header information and write local header to zip file */
- X#ifdef OS2
- X if ( dosify < 2 )
- X dosify = IsFileSystemFAT(z->name);
- X#endif /* OS2 */
- X
- X /* (Assume ext, cext, com, and zname already filled in.) */
- X z->vem = dosify ? 11 : /* Made under MSDOS by PKZIP 1.1 */
- X#ifdef VMS
- X 0x200 + REVISION; /* Made under VMS by this Zip */
- X#else /* !VMS */
- X#ifdef OS2
- X 0x600 + REVISION; /* Made under OS/2 by this Zip */
- X#else /* !OS2 */
- X 0x300 + REVISION; /* Made under Unix by this Zip */
- X#endif /* ?OS2 */
- X#endif /* ?VMS */
- X z->ver = 10; /* Need PKUNZIP 1.0 */
- X z->flg = (ush)g;
- X if (key != NULL)
- X z->flg |= 1;
- X z->lflg = z->flg;
- X z->how = h;
- X z->crc = c;
- X z->siz = s;
- X if (key != NULL)
- X z->siz += 12;
- X z->len = n;
- X z->nam = strlen(z->zname);
- X z->dsk = 0;
- X z->att = 0; /* Assume they're all binary */
- X z->atx = dosify ? a & 0xff : a; /* Attributes from filetime() */
- X if ((z->off = ftell(y)) == -1L)
- X return ZE_WRITE;
- X if ((r = putlocal(z, y)) != ZE_OK)
- X return r;
- X
- X /* Write stored, shrunk, or imploded file to zip file */
- X#ifndef EXPORT
- X if (key != NULL)
- X crypthead(key, z->crc, y);
- X#endif /* !EXPORT */
- X n = ftell(y); /* Save offset for logic check */
- X#ifndef NOIMPLODE
- X if (h == IMPLODE)
- X {
- X if ((r = imp_p2(y)) != ZE_OK)
- X return r;
- X imp_clear();
- X impact = 0;
- X }
- X else
- X#endif /* !NOIMPLODE */
- X if (h == SHRINK)
- X {
- X if ((r = shr_p2(y)) != ZE_OK)
- X return r;
- X shr_clear();
- X shract = 0;
- X }
- X else
- X {
- X if (!l)
- X zrew(f);
- X if ((b = malloc(BSZ)) == NULL)
- X return ZE_MEM;
- X while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
- X {
- X if (zfwrite(b, 1, k, y) != k)
- X {
- X free((voidp *)b);
- X return ZE_TEMP;
- X }
- X if (l)
- X break;
- X }
- X free((voidp *)b);
- X if (!l && zerr(f))
- X return ZE_READ;
- X if (!l)
- X zclose(f);
- X }
- X
- X /* Check length of compressed data */
- X if (ftell(y) != n + s)
- X return ZE_LOGIC;
- X
- X /* Done--clean up and leave */
- X if (noisy)
- X {
- X putchar('\n');
- X fflush(stdout);
- X }
- X return ZE_OK;
- X}
- X
- X#endif /* !UTIL */
- END_OF_FILE
- if test 10409 -ne `wc -c <'zipup.c'`; then
- echo shar: \"'zipup.c'\" unpacked with wrong size!
- fi
- # end of 'zipup.c'
- fi
- echo shar: End of archive 7 \(of 9\).
- cp /dev/null ark7isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 9 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-